home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / degaspic.lzh / degaspic / degaspic.c
Encoding:
C/C++ Source or Header  |  1993-09-13  |  11.8 KB  |  369 lines

  1. #include    <aesbind.h>
  2. #include    <gemfast.h>
  3. #include    <obdefs.h>
  4. #include    <macros.h>
  5. #include    <stdio.h>
  6. #include    <stdlib.h>
  7. #include    <string.h>
  8. #include    <vdibind.h>
  9.  
  10. /* this should really go into a header file for debugging stuff        */
  11. #ifndef        NDEBUG
  12. #ifdef        __TURBOC__
  13. static void _DEBUG(const char *s,...) \
  14.    {vfprintf(stderr,s,...);fprintf(stderr,"\n");}
  15. /*static void _DEBUGL(const char *s,...) \
  16.    {vfprintf(stderr,s,...);}*/
  17. #else
  18. static void _DEBUG(const char *s,...) \
  19.    {vfprintf(stderr,s,(__VA_LIST__)__builtin_next_arg()); \
  20.    fprintf(stderr,"\n");}
  21. /*static void _DEBUGL(const char *s,...) \
  22.    {vfprintf(stderr,s,(__VA_LIST__)__builtin_next_arg());}*/
  23. #endif
  24. #define     DEBUG(x)    _DEBUG x
  25. #define        DEBUGL(x)    _DEBUGL x
  26. #else
  27. #define        DEBUG(x)
  28. #define        DEBUGL(x)
  29. #endif
  30.  
  31. #define        BUFSIZE        512
  32.  
  33. typedef struct {
  34.     unsigned int    compression : 1;
  35.     unsigned int    reserved0    : 13;
  36.     unsigned int    resolution    : 2;
  37.     struct {
  38.         unsigned int reserved1    : 5;
  39.         unsigned int red        : 3;
  40.         unsigned int reserved2    : 1;
  41.         unsigned int green        : 3;
  42.         unsigned int reserved3    : 1;
  43.         unsigned int blue        : 3; } palette[16];
  44. } DegasPic;
  45.  
  46. static int vr_pal_trnfm(int vdihandle,unsigned short *colcnv,
  47.                         MFDB *source,MFDB *dest)
  48. /* convert standard to non-standard format, even if the amount of    */
  49. /* planes does not match; handle palette conversion for vdi colors;    */
  50. /* currently no more than sixteen vdicolors are supported (MAXCOL);    */
  51. /* you can provide an array with sixteen entries for converting        */
  52. /* your input colors to vdi colors.                                    */
  53. /* Warning! if transformation between different colors/planes has    */
  54. /* to be performed, this algorithm is very slow and (temporarly)    */
  55. /* memory expensive!                                                */
  56. {
  57.     #define        MAXPLANES        24
  58.     #define        MAXCOL            16
  59.  
  60.     static unsigned long    vditab[MAXCOL];    /* cache for speed-up    */
  61.     static int                dest_planes = -1;
  62.     static int                maxcol,trivial;
  63.     unsigned short            bios2vdi[MAXCOL];
  64.     unsigned long            col,lookup[MAXCOL];
  65.     MFDB                    tmp_mfdb = *source;
  66.  
  67.     if (source->fd_stand == dest->fd_stand ||    /*       ???         */
  68.         !source->fd_stand ||                    /* implementation    */
  69.         (1UL << source->fd_nplanes) > MAXCOL ||    /* restriction!        */
  70.         source->fd_nplanes > 8*sizeof(unsigned short) ||
  71.         dest->fd_nplanes > MAXPLANES) {            /*        "            */
  72.         /* Call standard vr_trnfm() function if extended handling is*/
  73.         /* not needed or not possible...                            */
  74.         vr_trnfm(vdihandle,source,dest);
  75.         return(1); }
  76.     if (dest_planes != dest->fd_nplanes) {    /* resolution change or    */
  77.         int                    plane;            /* uninitialized vdi    */
  78.         MFDB                m_std,m_nstd;    /* lookup table...        */
  79.         unsigned long        d_std[MAXPLANES],d_nstd[MAXCOL];
  80.         int                    pxy[8],trans_col[2];
  81.         dest_planes       = dest->fd_nplanes;
  82.         maxcol = (unsigned short)(min(MAXCOL,(1UL << dest_planes)));
  83.         m_nstd.fd_addr    = (long)d_nstd;
  84.         m_nstd.fd_w       = sizeof(unsigned long)*8;
  85.         m_nstd.fd_h       = 1;
  86.         m_nstd.fd_wdwidth = sizeof(unsigned long)/2;
  87.         m_nstd.fd_stand   = 0;
  88.         m_nstd.fd_nplanes = dest_planes;
  89.         m_nstd.fd_r1      =
  90.         m_nstd.fd_r2      =
  91.         m_nstd.fd_r3      = 0;
  92.         m_std             = m_nstd;
  93.         m_std.fd_addr     = (long)d_std;
  94.         m_std.fd_stand    = 1;
  95.         m_std.fd_nplanes  = 1;                 /* for vrt_cpyfm        */
  96.         d_std[0]          = ~0;
  97.         memset(pxy,0,sizeof(pxy));
  98.         trans_col[1]      = 0;
  99.         memset(d_nstd,0,sizeof(d_nstd));
  100.         for (trans_col[0] = 0; trans_col[0] < maxcol; trans_col[0]++) {
  101.             pxy[4] = pxy[6] = (8*(int)sizeof(unsigned long))-trans_col[0]-1;
  102.             vrt_cpyfm(vdihandle,MD_TRANS,pxy,&m_std,&m_nstd,trans_col); }
  103.         m_std.fd_nplanes  = dest_planes;
  104.         vr_trnfm(vdihandle,&m_nstd,&m_std);
  105.         for (col = 0; col < maxcol; col++) {
  106.             vditab[col] = 0;
  107.             for (plane = 0; plane < dest_planes; plane++)
  108.                 if (d_std[plane] & (1UL << col))
  109.                     vditab[col] |= 1UL << plane; }
  110.         for (col = maxcol; col < MAXCOL; col++)
  111.             vditab[col] = vditab[maxcol-1]; }
  112.     trivial = 1;
  113.     if (colcnv) {
  114.         int        black = min(15,(int)((1UL << source->fd_nplanes)-1));
  115.         for (col = MAXCOL; col--;)
  116.             bios2vdi[col] = col < black ? colcnv[col] :
  117.                             col == black ? 1 : colcnv[col]; }
  118.     for (col = MAXCOL; col--;)
  119.         if ((lookup[col] = colcnv ?
  120.             vditab[bios2vdi[col]] : vditab[col]) != col)
  121.             trivial = 0;
  122.     if ((!trivial || source->fd_nplanes != dest_planes)) {
  123.         if ((tmp_mfdb.fd_addr = (long)malloc(2L*
  124.             (long)source->fd_wdwidth*(long)source->fd_h*
  125.             (long)dest_planes)) == 0L) {
  126.             /* Sorry! Algorithm for splitting bit blocks and con-    */
  127.             /* serving some memory not yet implemented!                */
  128.             return(0); /* fail */ }
  129.         else {
  130.             unsigned long          offset,index;
  131.             unsigned short         plane,bit;
  132.             unsigned short        *s_word,*ptr,*d_word;
  133.             s_word = (unsigned short *)source->fd_addr;
  134.             d_word = (unsigned short *)tmp_mfdb.fd_addr;
  135.             offset = (unsigned long)source->fd_h*
  136.                      (unsigned long)source->fd_wdwidth;
  137.             /* This loop *needs* optimization! Assembly language    */
  138.             /* might be a really good idea :-)                        */
  139.             for (index = offset; index--; s_word++,d_word++) {
  140.                 for (plane = dest_planes, ptr = d_word;
  141.                      plane--;
  142.                      *ptr = 0, ptr += offset);
  143.                 for (bit = 8*sizeof(unsigned short); bit--;) {
  144.                     for (ptr = s_word, col = 0, plane = 0;
  145.                          plane < source->fd_nplanes;
  146.                          plane++, ptr += offset) {
  147.                         if (*ptr & (1U << bit))
  148.                             col |= 1UL << plane; }
  149.                     col = lookup[col%MAXCOL];
  150.                     for (ptr = d_word, plane = 0;
  151.                          plane < dest_planes;
  152.                          plane++, ptr += offset)
  153.                         if (col & (1U << plane))
  154.                             *ptr |= 1U << bit; } }
  155.             tmp_mfdb.fd_nplanes = dest_planes;
  156.             vr_trnfm(vdihandle,&tmp_mfdb,dest);
  157.             free((void *)tmp_mfdb.fd_addr); } }
  158.     else {
  159.         vr_trnfm(vdihandle,source,dest); }
  160.     return(1);
  161.     
  162.     #undef    MAXPLANES
  163.     #undef    MAXCOL
  164. }
  165.  
  166. static void separatebitplanes(MFDB *source,MFDB *dest)
  167. /* basically the same function as vr_trnfm(nstd,std) for standard    */
  168. /* ST video modes; but you cannot call vr_trnfm() for converting    */
  169. /* Degas Elite images, if you do not want to make assumption on the    */
  170. /* video system...                                                    */
  171. {
  172.     unsigned short    *s,*d,*ptr;
  173.     unsigned long    offset,index;
  174.     int                plane;
  175.     
  176.     offset = (long)source->fd_wdwidth*(long)source->fd_h;
  177.     s = (unsigned short *)source->fd_addr;
  178.     d = (unsigned short *)dest->fd_addr;
  179.     for (index = offset; index--; d++) {
  180.         ptr = d;
  181.         for (plane = source->fd_nplanes; plane--; ptr += offset)
  182.             *ptr = *s++; }
  183.     return;
  184. }
  185.  
  186. static MFDB *loaddegas(int vdihandle,char *fname)
  187. {
  188.     #define DATA(x)        ((unsigned char *)((DegasPic *)(x)+1))
  189.     #define getbyte()    (pos < len ? buffer[pos++] : \
  190.                              len <= 0 ? -1 : \
  191.                              (pos = 0,len = (int)fread(buffer,1L,BUFSIZE,file)) \
  192.                              <= 0 ? -1 : buffer[pos++])
  193.     static unsigned short    colcnv[4][16] = {
  194.                 /* adapt this table as needed (your mileage may vary!)*/
  195.                 { 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1},
  196.                 { 0, 2, 2, 2, 2, 2, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1},
  197.                 { 0, 2, 3, 6, 4, 7, 5, 8, 1, 2, 3, 6, 4, 7, 5, 1},
  198.                 { 0, 2, 3, 6, 4, 7, 5, 8, 9,10,11,14,12,15,13, 1}};
  199.     static unsigned char buffer[BUFSIZE];
  200.     FILE        *file;
  201.     int            planes,workout[57];
  202.     int            pos,len;
  203.     DegasPic    *source;
  204.     MFDB        *m_source,m_dest;
  205.     int            splanes,x,y,p,b,w,h,c,inc,data = 0;
  206.     unsigned char *d;
  207.  
  208.     vq_extnd(vdihandle,1,workout);
  209.     planes = workout[4];
  210.     if ((file = fopen(fname,"rb")) == NULL) {
  211.         DEBUG(("file not found"));
  212.         return(0); }
  213.     if ((source = (void *)calloc(1,sizeof(DegasPic)+32000)) == NULL) {
  214.         DEBUG(("out of memory"));
  215.         fclose(file);
  216.         return(0); }
  217.     if ((len = (int)fread(buffer,1L,BUFSIZE,file)) < sizeof(DegasPic) ||
  218.         source->resolution == 3) {
  219.         DEBUG(("illegal file format"));
  220.         free(source);
  221.         fclose(file);
  222.         return(0); }
  223.     *source = *(DegasPic *)&buffer;
  224.     pos = (int)sizeof(DegasPic);
  225.     splanes = 1 << (2 - source->resolution);
  226.     if (!source->compression) {
  227.         memcpy(DATA(source),buffer+pos,BUFSIZE-sizeof(DegasPic));
  228.         if (fread(DATA(source)+BUFSIZE-sizeof(DegasPic),1L,
  229.             32000-BUFSIZE+sizeof(DegasPic),file) !=
  230.             32000-BUFSIZE+sizeof(DegasPic)) {
  231.             DEBUG(("file too short"));
  232.             free(source);
  233.             fclose(file);
  234.             return(0); }
  235.         switch (source->resolution) {
  236.             case 0:
  237.                 w = 320; h = 200; break;
  238.             case 1:
  239.                 w = 640; h = 200; break;
  240.             case 2:
  241.                 w = 640; h = 400; break;
  242.             default:
  243.                 DEBUG(("this cannot happen!"));
  244.                 free(source);
  245.                 fclose(file);
  246.                 return(0); }
  247.         fclose(file); }
  248.     else {
  249.         source->compression = 0;
  250.         switch (source->resolution) {
  251.             case 0:
  252.                 w = 320; h = 200; break;
  253.             case 1:
  254.                 w = 640; h = 200; break;
  255.             case 2:
  256.                 w = 640; h = 400; break;
  257.             default:
  258.                 DEBUG(("this cannot happen!"));
  259.                 free(source);
  260.                 fclose(file);
  261.                 return(0); }
  262.         d = DATA(source);
  263.         c = 0;
  264.         inc = 1;
  265.         for (y = 0; y < h; y++, d += (w/8-2)*splanes)
  266.             for (p = 0; p < splanes; p++,d -= (w/8)*splanes-2)
  267.                 for (x = 0; x < w/16; x++, d += 2*(splanes-1))
  268.                     for (b = 0; b < 2; b++,d++) {
  269.                         if (!c) {
  270.                             do {
  271.                                 c = getbyte();
  272.                                 if (c == 128)
  273.                                     DEBUG(("NOP found in compressed data"));
  274.                                 else if (c == -1) {
  275.                         eof:        DEBUG(("insufficient data"));
  276.                                     free(source);
  277.                                     fclose(file);
  278.                                     return(0); }
  279.                             } while (c == 128);
  280.                             if (c > 128) {
  281.                                 c = 257 - c; inc = 0;
  282.                                 if ((data = getbyte()) == -1)
  283.                                     goto eof; }
  284.                             else {
  285.                                 c += 1; inc = 1; } }
  286.                         if (inc && ((data = getbyte()) == -1))
  287.                             goto eof;
  288.                         *d = data; c--; }
  289.         fclose(file); }
  290.     m_source            = (MFDB *)malloc(sizeof(MFDB)+
  291.                           (long)w/8L*(long)h*
  292.                           (long)max(planes,splanes));
  293.     if (m_source == NULL) {
  294.         free(DATA(source));
  295.         return(0); }
  296.     m_source->fd_addr   = (long)DATA(source);
  297.     m_source->fd_w      = w;
  298.     m_source->fd_h      = h;
  299.     m_source->fd_wdwidth= m_source->fd_w / 16;
  300.     m_source->fd_stand  = 0;
  301.     m_source->fd_nplanes= splanes;
  302.     m_source->fd_r1     =
  303.     m_source->fd_r2     =
  304.     m_source->fd_r3     = 0;
  305.     m_dest              = *m_source;
  306.     m_dest.fd_addr      = (long)(m_source+1);
  307.     m_dest.fd_stand     = 1;
  308.     separatebitplanes(m_source,&m_dest);
  309.     memcpy(DATA(source),m_source+1,
  310.            (long)w/8L*(long)h*(long)splanes);
  311.     m_dest.fd_addr      = (long)DATA(source);
  312.     m_dest.fd_stand     = 1;
  313.     m_source->fd_addr   = (long)(m_source+1);
  314.     m_source->fd_nplanes= planes;
  315.     m_source->fd_stand  = 0;
  316.      if (!vr_pal_trnfm(vdihandle,colcnv[splanes > 4 ? 3 : splanes-1],
  317.          &m_dest,m_source)) {
  318.         free(source);
  319.          free((void *)m_source);
  320.          return(0); }
  321.     free(source);
  322.     return(m_source);
  323.     
  324.     #undef    DATA
  325.     #undef    getbyte
  326. }
  327.  
  328. int        main(int argc,char *argv[])
  329. {
  330.     int            vdihandle,workin[11],workout[57];
  331.     int            x,y,w,h,pxy[8];
  332.     MFDB        scr,*img;
  333.     
  334.     appl_init();
  335.     memset(workin,0,sizeof(workin));
  336.     workin[0] = vdihandle = graf_handle(&x,&y,&w,&h);
  337.     workin[10] = 2;
  338.     v_opnvwk(workin,&vdihandle,workout);
  339.     x = y = 0;
  340.     w = workout[0] + 1;
  341.     h = workout[1] + 1;
  342.     img = loaddegas(vdihandle,argc == 2 ? argv[1] : "DEMO.PC1");
  343.     if (img != NULL) {
  344.         wind_update(BEG_UPDATE);
  345.         wind_update(BEG_MCTRL);
  346.         form_dial(FMD_START,0,0,0,0,x,y,w,h);
  347.         scr.fd_addr = 0;
  348.         pxy[6] = pxy[2] = (pxy[4] = pxy[0] = x) + w - 1;
  349.         pxy[7] = pxy[3] = (pxy[5] = pxy[1] = y) + h - 1;
  350.         graf_mouse(M_OFF,0);
  351.         vro_cpyfm(vdihandle,ALL_WHITE,pxy,&scr,&scr);
  352.         pxy[2] = (pxy[0] = 0) + img->fd_w - 1;
  353.         pxy[3] = (pxy[1] = 0) + img->fd_h - 1;
  354.         pxy[6] = (pxy[4] = (w - img->fd_w) / 2) + img->fd_w - 1;
  355.         pxy[7] = (pxy[5] = (h - img->fd_h) / 2) + img->fd_h - 1;
  356.         vro_cpyfm(vdihandle,S_ONLY,pxy,img,&scr);
  357.         graf_mouse(M_ON,0);
  358.         evnt_keybd();
  359.         form_dial(FMD_FINISH,0,0,0,0,x,y,w,h);
  360.         wind_update(END_MCTRL);
  361.         wind_update(END_UPDATE);
  362.         free(img); }
  363.     else
  364.         DEBUG(("picture could not be loaded"));
  365.     v_clsvwk(vdihandle);
  366.     appl_exit();
  367.     return(0);
  368. }
  369.